package com.lantu.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lantu.utils.collection.CollectionUtils;

import java.util.List;

/**
 * Bean 工具类
 *
 * 1. 默认使用 {@link cn.hutool.core.bean.BeanUtil} 作为实现类，虽然不同 bean 工具的性能有差别，但是对绝大多数同学的项目，不用在意这点性能
 * 2. 针对复杂的对象转换，可以搜参考 AuthConvert 实现，通过 mapstruct + default 配合实现
 *
 * @author 宾宇煌
 */
public class BeanUtils {

    private static CopyOptions createCopyOptions(boolean ignoreNull, String... ignoreProperties) {
        CopyOptions copyOptions = CopyOptions.create();
        if (ignoreNull) {
            copyOptions.ignoreNullValue();
        }
        if (ignoreProperties != null && ignoreProperties.length > 0) {
            copyOptions.setIgnoreProperties(ignoreProperties);
        }
        return copyOptions;
    }

    public static <T> T toBean(Object source, Class<T> targetClass) {
        return BeanUtil.toBean(source, targetClass);
    }

    public static <T> T toBean(Object source, Class<T> targetClass, boolean ignoreNull) {
        return BeanUtil.toBean(source, targetClass, createCopyOptions(ignoreNull));
    }

    public static <T> T toBean(Object source, Class<T> targetClass, String... ignoreProperties) {
        return BeanUtil.toBean(source, targetClass, createCopyOptions(false, ignoreProperties));
    }

    public static <T> T toBean(Object source, Class<T> targetClass, boolean ignoreNull, String... ignoreProperties) {
        return BeanUtil.toBean(source, targetClass, createCopyOptions(ignoreNull, ignoreProperties));
    }

    public static <S, T> List<T> toBean(List<S> source, Class<T> targetType) {
        return CollectionUtils.convertList(source, s -> toBean(s, targetType));
    }

    public static <S, T> List<T> toBean(List<S> source, Class<T> targetType, boolean ignoreNull) {
        return CollectionUtils.convertList(source, s -> toBean(s, targetType, ignoreNull));
    }

    public static <S, T> List<T> toBean(List<S> source, Class<T> targetType, String... ignoreProperties) {
        return CollectionUtils.convertList(source, s -> toBean(s, targetType, ignoreProperties));
    }

    public static <S, T> List<T> toBean(List<S> source, Class<T> targetType, boolean ignoreNull, String... ignoreProperties) {
        return CollectionUtils.convertList(source, s -> toBean(s, targetType, ignoreNull, ignoreProperties));
    }

    public static <S, T> Page<T> toBean(Page<S> source, Class<T> targetType, boolean ignoreNull, String... ignoreProperties) {
        if (source == null) {
            return null;
        }
        Page<T> page = new Page<>(source.getCurrent(), source.getSize());
        page.setTotal(source.getTotal());
        page.setPages(source.getPages());
        page.setCurrent(source.getCurrent());
        page.setSize(source.getSize());
        List<T> list = toBean(source.getRecords(), targetType, ignoreNull, ignoreProperties);
        page.setRecords(list);
        return page;
    }

    public static <S, T> Page<T> toBean(Page<S> source, Class<T> targetType) {
        return toBean(source, targetType, false);
    }

    public static <S, T> Page<T> toBean(Page<S> source, Class<T> targetType, boolean ignoreNull) {
        return toBean(source, targetType, ignoreNull, (String[]) null);
    }

    public static <S, T> Page<T> toBean(Page<S> source, Class<T> targetType, String... ignoreProperties) {
        return toBean(source, targetType, false, ignoreProperties);
    }

}
